﻿using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.MultiTouch;
using OpenQA.Selenium.Appium.Service;
using SimulationCenter.Tasks.Svrs;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using Tools;

namespace SimulationCenter.Scripts
{
    /// <summary>
    /// 检索指定设备指定公众号中的消息
    /// </summary>
    public class FetchSubscriptionMsgsScriptExecutor : ScriptExecutorBase
    {
        private readonly string _subscription;
        private readonly ISubscriptionSvr _subscriptionSvr;
        private string _subscriptionTitle = null;
        private string _preCapture = null;
        private string _curCapture = null;
        private int _disactive = 0;
        private readonly System.Timers.Timer _timer;

        public FetchSubscriptionMsgsScriptExecutor(AppiumLocalService localService, ISubscriptionSvr subscriptionSvr, string serial, string subscription)
            : base(localService, serial)
        {
            _subscriptionSvr = subscriptionSvr;
            _subscription = subscription;

            _subscriptionTitle = _subscription;

            _timer = new System.Timers.Timer(60 * 1000);
            _timer.Elapsed += _timer_Elapsed;
        }

        protected override void Start()
        {
            // 点击搜索按钮
            var searchButton = Driver.FindElement(Const.SearchButtonXpath);
            searchButton.Click();

            // 输入公众号名称
            var searchTextBox = Driver.FindElement(Const.SearchTextBoxId);
            searchTextBox.SendKeys(_subscription);

            // 隐藏键盘
            SafeHideKeyboard();

            // 查找关注公众号
            if (!HasSubscribed(_subscription, out var element))
            {
                // 没有关注此公众号, 进入公众号详情
                MoveIntoSubscriptionProfile(_subscription);

                Subscribe();
            }
            else
            {
                // 进入公众号聊天页
                element.Click();

                // 进入详情页
                MoveToProfilePage();
            }

            // 滚动至底部， 点击全部消息
            ScrollToProfileBottomAndClickButton();

            // 启动终端卡壳检测服务
            _timer.AutoReset = true;
            _timer.Enabled = true;
            _timer.Start();
        }

        /// <summary>
        /// 释放
        /// </summary>
        public override void Dispose()
        {
            _timer?.Stop();
            _timer?.Dispose();

            base.Dispose();
        }

        #region privates

        /// <summary>
        /// 是否已经关注此账号
        /// </summary>
        /// <param name="subscription"></param>
        /// <param name="element"></param>
        /// <returns></returns>
        private bool HasSubscribed(string subscription, out AppiumWebElement element)
        {
            element = null;

            try
            {
                var locator = new ByAndroidUIAutomator($"new UiSelector().text(\"{subscription}\")");
                var elements = Driver.FindElements(locator);

                if (elements.Count > 1)
                {
                    element = elements.Last();
                    return true;
                }

                return false;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 搜索公众号进入详情页（在已经搜索的前提下）
        /// </summary>
        /// <param name="subscription"></param>
        private void MoveIntoSubscriptionProfile(string subscription)
        {
            // 点击搜一搜按钮， 进入搜索结果页
            var element = Driver.FindElement(Const.SearchSubscriptionsId);
            element.Click();

            // 等待搜索结果加载
            Thread.Sleep(TimeSpan.FromSeconds(15));

            // 切换至公众号 Tab
            new TouchAction(Driver).Tap(185, 200).Perform();

            Thread.Sleep(TimeSpan.FromSeconds(3));

            // 点击搜索的第一条公众号选项
            new TouchAction(Driver).Tap(350, 400).Perform();

            Thread.Sleep(TimeSpan.FromSeconds(3));

            // 确认当前是否为公众号详情页
            //if (!Const.SubscriptionInfoPage.Equals(Driver.CurrentActivity,
            //    StringComparison.CurrentCultureIgnoreCase))
            //    throw new ScriptExecutorException($"检索公众号 '{subscription}' 失败", "当前页面不为公众号详情页");
        }

        /// <summary>
        ///  关注公众号
        /// </summary>
        private void Subscribe()
        {
            // 关注公众号
            try
            {
                var locator = new ByAndroidUIAutomator("new UiSelector().text(\"关注公众号\")");
                var element = Driver.FindElement(locator);
                element.Click();
            }
            catch (Exception)
            {
                var locator = new ByAndroidUIAutomator("new UiSelector().text(\"进入公众号\")");
                var element = Driver.FindElement(locator);
                element.Click();
            }

            Thread.Sleep(TimeSpan.FromSeconds(5));

            // 进入详情页
            MoveToProfilePage();
        }

        /// <summary>
        /// 跳转到公众号详情页面
        /// </summary>
        private void MoveToProfilePage()
        {
            var profile = Driver.FindElement(Const.SubscriptionProfileId);
            profile.Click();

            Thread.Sleep(TimeSpan.FromSeconds(3));

            // 获取公众号标题
            var title = Driver.FindElement(Const.SubscriptionProfileTitle);
            if (!_subscriptionTitle.Equals(title.Text))
            {
                // 如果 _subscriptionTitle 与 公众号标题不同， 
                // 说明录入的是 公众号 的 微信号， 此时需要进行绑定
                // FetchMoreInfo();

                _subscriptionSvr.BindSubscription(_subscriptionTitle, title.Text);
            }
        }

        /// <summary>
        /// 获取公众号更多资料
        /// </summary>
        private void FetchMoreInfo()
        {
            // 查询当前公众号是否绑定了 ScSubscription 信息
            var scSubscription = _subscriptionSvr.FindSubscription(_subscription);
            if (scSubscription != null) return;

            // 点击右上角公众号详情
            var rightMenu = Driver.FindElement(Const.SubscriptionInfoMenuId);
            rightMenu.Click();

            Thread.Sleep(TimeSpan.FromSeconds(3));

            // 点击更多资料
            var locator = new ByAndroidUIAutomator("new UiSelector().text(\"更多资料\")");
            var moreInfo = Driver.FindElement(locator);
            moreInfo.Click();

            if (!Const.SubscriptionMoreInfoPage.Equals(Driver.CurrentActivity,
                StringComparison.CurrentCultureIgnoreCase))
                throw new ScriptExecutorException($"获取公众号 '{_subscription}' 的更多资料失败", "当前页面不为公众号更多资料页面");

            var moreInfos = Driver.FindElements(Const.SubscriptionMoreInfos);

            foreach (var item in moreInfos)
            {
                var title = item.FindElementById("android:id/title");
                if ("微信号".Equals(title.Text))
                {
                    var subscriptionId = item.FindElementById("android:id/summary").Text;

                    // _subscriptionSvr.BindSubscription(subscriptionNo)
                    break;
                }
            }

            // 返回
            var back = Driver.FindElement(Const.SubscriptionWebViewBackId);
            back.Click();

            Thread.Sleep(TimeSpan.FromSeconds(3));
        }

        /// <summary>
        /// 全部消息按钮是否可见
        /// </summary>
        /// <returns></returns>
        private bool IsAllMessagesButtonVisible(out AppiumWebElement element)
        {
            element = null;

            try
            {
                element = Driver.FindElement(Const.LoadAllMessagesId);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 公众号详情页滑动至最底部
        /// </summary>
        private void ScrollToProfileBottomAndClickButton()
        {
            AppiumWebElement element;

            while (!IsAllMessagesButtonVisible(out element))
            {
                var args = new Dictionary<string, object>
                {
                    ["command"] = "input swipe",
                    ["args"] = $"50 {ScreenSize.Height * 0.9 } 50 { ScreenSize.Height * 0.1 } 1000",
                    ["includeStderr"] = true,
                    ["timeout"] = 10000
                };

                Driver.ExecuteScript("mobile:shell", args);

                Thread.Sleep(TimeSpan.FromSeconds(3));
            }

            element.Click();
        }

        private void SafeHideKeyboard()
        {
            try
            {
                Driver.HideKeyboard();
            }
            catch (Exception)
            {
                // ignore
            }
        }

        /// <summary>
        /// 保存屏幕截图
        /// </summary>
        private void SaveCapture()
        {
            if (Driver == null || Status == ExecutorStatus.Quit) return;

            var capture = Driver.GetScreenshot();

            var directory = "captures";
            if (!Directory.Exists(directory))
                Directory.CreateDirectory(directory);

            directory = $"{directory}{Path.DirectorySeparatorChar}{DateTime.Now:yyyy-MM-dd}";
            if (!Directory.Exists(directory))
                Directory.CreateDirectory(directory);

            _curCapture = $"{directory}{Path.DirectorySeparatorChar}{Serial}_{DateTime.Now:HHmmss}.png";
            capture.SaveAsFile(_curCapture, ScreenshotImageFormat.Png);

            if (string.IsNullOrEmpty(_preCapture))
            {
                _preCapture = _curCapture;
                return;
            }
        }

        private void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            IsActive();
        }

        /// <summary>
        /// 检测终端是否活动
        /// </summary>
        private void IsActive()
        {
            if (Driver == null || Status == ExecutorStatus.Quit) return;

            try
            {
                SaveCapture();

                if (string.IsNullOrEmpty(_preCapture) ||
                    string.IsNullOrEmpty(_curCapture) ||
                    _preCapture.Equals(_curCapture)) return;

                // 计算两次截屏相似度
                Console.WriteLine($"设备：{Serial}, 计算两次截屏相似度:");
                Console.WriteLine($"previous : {_preCapture}");
                Console.WriteLine($"current：{_curCapture}");

                if (!ImageComparator.Compare(_preCapture, _curCapture, out var degree))
                {
                    Console.WriteLine($"设备：{Serial}, 计算两次截屏相似度失败");
                    return;
                }

                _preCapture = _curCapture;

                Console.WriteLine($"设备：{Serial}, 最近两次截屏图片相似度: {degree * 100}%");

                if (degree <= 0.99)
                {
                    Console.WriteLine($"设备：{Serial}, 最近两次截屏图片相似度低于: 99%， 预警数置零");
                    _disactive = 0;
                }
                else
                {
                    _disactive++;
                    Console.WriteLine($"设备：{Serial}, 最近两次截屏图片相似度高于: 99%， 目前预警数：{_disactive}");
                }

                if (_disactive >= 3)
                {
                    var error = $"设备：{Serial}, 在最近3次截屏图片相似度对比均高于99%";
                    Console.WriteLine(error);

                    _timer.Enabled = false;
                    _timer.Stop();
                    TriggerErrorEvent(new Exception(error));
                }
            }
            catch (Exception e)
            {
                // ignore
                Console.WriteLine($"IsActive error :{e}");
            }
        }

        #endregion
    }
}
